from observable import notify
from utils import RenderRepr, is_solid


class Object:  # TODO: Add destructor.
    render_repr = RenderRepr("!", (255, 0, 0), (127, 0, 0))
    render_repr.hidden_version = render_repr
    is_solid = False
    target_layer = None

    def __init__(self):
        super().__init__()
        self.tile = None

    def move_to_tile(self, target_tile):
        # There should be some checks or whatever maybe.
        self.tile.level.move(self, self.tile, target_tile, self.target_layer)
        self.tile.all_call("on_left", self)
        self.tile = target_tile
        self.tile.all_call("on_entered", self)

    def remove_from_map(self):
        self.tile.remove(self)
        self.tile.all_call("on_left", self)
        self.tile = None

    def place_on_map(self, target_tile):
        self.tile = target_tile
        if self.target_layer:
            self.tile.add(self, self.target_layer)
        else:
            self.tile.try_add(self)
        self.tile.all_call("on_entered", self)

    def can_enter(self, tile):
        return True

    @property
    def game(self):
        return self.tile.level.whole_map.game

    @property
    def x(self):
        return self.tile.x

    @property
    def y(self):
        return self.tile.y

# class StaticObject(Object):
#     def __init__(self):
#         super().__init__()


class Wall(Object):
    target_layer = "wall"
    is_solid = True
    is_transparent = False

    def can_enter(self, tile):  # Probably shouldn't be here
        if not is_solid(tile["floor"].obj):
            return False
        if len(tile["characters"]) > 0:
            return False
        if is_solid(tile["wall"].obj):
            return False
        return True


class Floor(Object):
    target_layer = "floor"

    def can_enter(self, tile):
        return not is_solid(tile["floor"].obj)


class Stuff(Object):
    target_layer = "stuff"

    def can_enter(self, tile):  # Probably shouldn't be here
        if not is_solid(tile["floor"].obj):
            return False
        if len(tile["characters"]) > 0:
            return False
        if is_solid(tile["wall"].obj):
            return False
        return True


class Item(Object):
    target_layer = "items"

    def __init__(self):
        super().__init__()
        self.effects = {}  # Effects on character holding item.
        # {"name_of_attribute": ("type_of_application", value)}
        # "type_of_application" can be "*", "+", "fun"

    def can_enter(self, tile):  # Probably shouldn't be here
        if not is_solid(tile["floor"].obj):
            return False
        if is_solid(tile["wall"].obj):
            return False
        return True

    def picked_up(self, who):
        self.remove_from_map()
        who.inventory.append(self)

    def dropped(self, who):
        who.inventory.remove(self)
        self.place_on_map(who.tile)
